package com.huahan.auth.security.config;

import com.huahan.auth.Utils.RedisHelper;
import com.huahan.auth.filter.HuahanCheckHeaderTokenFilter;
import com.huahan.auth.filter.HuahanLoginVerifyLimitFilter;
import com.huahan.auth.filter.HuahanSmsVerifyLimitFilter;
import com.huahan.auth.security.component.MyRedisTokenStore;
import com.mall.common.constant.AnonymousUrlConstant;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter implements InitializingBean {
    /**
     * 保存匿名访问的 url，表示可以不需要权限直接可以访问
     */
    private final List<String> anonymousAntPatterns = new ArrayList<>();
    @Value("${OAuth2.resourceId}")
    private String resourceId;
    @Resource
    private AuthenticationFailureHandler authenticationFailureHandler;
    @Resource
    private AccessDeniedHandler accessDeniedHandler;
    @Resource
    private AuthenticationEntryPoint authenticationEntryPoint;
    @Resource
    private RedisHelper redisHelper;
    /**
     * 需要加上，避免循环依赖问题
     */
    @Lazy
    @Resource
    private MyRedisTokenStore tokenStore;

    @Override
    public void afterPropertiesSet() throws ServletException {
        anonymousAntPatterns.add(AnonymousUrlConstant.LOGIN_IN_URL);
        anonymousAntPatterns.add(AnonymousUrlConstant.LOGIN_OUT_URL);
        anonymousAntPatterns.add(AnonymousUrlConstant.SYS_LOGIN_OUT_URL);
        anonymousAntPatterns.add(AnonymousUrlConstant.REGISTER_URL);
        anonymousAntPatterns.add(AnonymousUrlConstant.LOGIN_STATUS_URL);
        anonymousAntPatterns.add(AnonymousUrlConstant.GENERATOR);
        anonymousAntPatterns.add(AnonymousUrlConstant.REFRESH_TOKEN_URL);
        anonymousAntPatterns.add(AnonymousUrlConstant.VERIFY_URL);
        anonymousAntPatterns.add(AnonymousUrlConstant.ADMIN_URL);
        anonymousAntPatterns.add(AnonymousUrlConstant.ADMIN_LOGIN_URL);
        anonymousAntPatterns.add(AnonymousUrlConstant.MENU_URL);
        anonymousAntPatterns.add(AnonymousUrlConstant.PERMS_LIST);
        anonymousAntPatterns.add(AnonymousUrlConstant.SYS_File);
        anonymousAntPatterns.add(AnonymousUrlConstant.SYS_Files);
        anonymousAntPatterns.add(AnonymousUrlConstant.HUAHAN_TEST);
        anonymousAntPatterns.add(AnonymousUrlConstant.APP_AUTH);
        anonymousAntPatterns.add(AnonymousUrlConstant.TOKEN_URL);

        //B端
        anonymousAntPatterns.add(AnonymousUrlConstant.B_HOME);
        anonymousAntPatterns.add(AnonymousUrlConstant.B_ZONE);
        anonymousAntPatterns.add(AnonymousUrlConstant.B_LOGIN);
        anonymousAntPatterns.add(AnonymousUrlConstant.B_INDEX);
        anonymousAntPatterns.add(AnonymousUrlConstant.B_LOGIN_dd);
        anonymousAntPatterns.add(AnonymousUrlConstant.B_GOODS);
        //c端
        anonymousAntPatterns.add(AnonymousUrlConstant.C_LOGIN);
        anonymousAntPatterns.add(AnonymousUrlConstant.C_HOME);
        anonymousAntPatterns.add(AnonymousUrlConstant.C_HGOODS);
        anonymousAntPatterns.add(AnonymousUrlConstant.FLASH_SALE_GOODS_LIST);
        anonymousAntPatterns.add(AnonymousUrlConstant.FLASH_SALE_SESSION_LIST);
        anonymousAntPatterns.add(AnonymousUrlConstant.FLASH_SALE_GOODS_MSG);
        anonymousAntPatterns.add(AnonymousUrlConstant.APP_GOODS_CATEGORY_MSG);
        anonymousAntPatterns.add(AnonymousUrlConstant.APP_BUSINESS);
        anonymousAntPatterns.add(AnonymousUrlConstant.APP_EXPLAINSETTING_GET);
        //品牌特惠
        anonymousAntPatterns.add(AnonymousUrlConstant.BRAND_DISCOUNTS_LIST);
        anonymousAntPatterns.add(AnonymousUrlConstant.BUSINESS_INFO);
        anonymousAntPatterns.add(AnonymousUrlConstant.GET_GENERATE_LIST);
        anonymousAntPatterns.add(AnonymousUrlConstant.APP_GOODS_INFO_LIST);
        //省市区
        anonymousAntPatterns.add(AnonymousUrlConstant.SELECT_REGIONTREE);

        //三方
        anonymousAntPatterns.add(AnonymousUrlConstant.SAN_LOGIN);
        anonymousAntPatterns.add(AnonymousUrlConstant.SAN_REFRESH);
        anonymousAntPatterns.add(AnonymousUrlConstant.SYNC_ZZRY_DATA);

        anonymousAntPatterns.add(AnonymousUrlConstant.EXCEL);
        anonymousAntPatterns.add(AnonymousUrlConstant.ExcelORDER);
        anonymousAntPatterns.add(AnonymousUrlConstant.invoicing);
        anonymousAntPatterns.add(AnonymousUrlConstant.pay);
        anonymousAntPatterns.add(AnonymousUrlConstant.TEST);
        anonymousAntPatterns.add(AnonymousUrlConstant.PAYJHREFUND);
        anonymousAntPatterns.add(AnonymousUrlConstant.NOTIFY);
        //售后补货
        anonymousAntPatterns.add(AnonymousUrlConstant.REISSUE_GOODS);
        anonymousAntPatterns.add(AnonymousUrlConstant.REISSUE_SAVE);
        anonymousAntPatterns.add(AnonymousUrlConstant.KD);

        //砍价
        anonymousAntPatterns.add(AnonymousUrlConstant.SEARCHBARGAININGGOODSCLASSIFICATIONLIST);
        anonymousAntPatterns.add(AnonymousUrlConstant.SEARCHBARGAININGGOODSPAGELIST);
        anonymousAntPatterns.add(AnonymousUrlConstant.SEARCHBARGAININGGOODSINFO);
        anonymousAntPatterns.add(AnonymousUrlConstant.SEARCHBARGAININGINFO);

        //拼团
        anonymousAntPatterns.add(AnonymousUrlConstant.APPGROUPACTIVITYSEARCHGROUPGOODSCLASSIFICATIONLIST);
        anonymousAntPatterns.add(AnonymousUrlConstant.APPGROUPACTIVITYSEARCHGROUPGOODSPAGELIST);
        anonymousAntPatterns.add(AnonymousUrlConstant.APPGROUPACTIVITYSEARCHGROUPGOODSINFO);
        anonymousAntPatterns.add(AnonymousUrlConstant.APPGROUPGETGROUPDETAILSHARE);
        anonymousAntPatterns.add(AnonymousUrlConstant.ES_GOODS_PC);

        //限时折扣
        anonymousAntPatterns.add(AnonymousUrlConstant.SEARCHDISCOUNTGOODSCLASSIFICATIONLIST);
        anonymousAntPatterns.add(AnonymousUrlConstant.SEARCHDISCOUNTGOODSPAGELIST);
        anonymousAntPatterns.add(AnonymousUrlConstant.SEARCHDISCOUNTGOODSINFO);

        //团购
        anonymousAntPatterns.add(AnonymousUrlConstant.APPTEAMSEARCHTEAMGOODSCLASSIFICATIONLIST);
        anonymousAntPatterns.add(AnonymousUrlConstant.APPTEAMSEARCHTEAMGOODSPAGELIST);
        anonymousAntPatterns.add(AnonymousUrlConstant.APPTEAMSEARCHTEAMGOODSINFO);
        //pc 商家详情页
        anonymousAntPatterns.add(AnonymousUrlConstant.SUPPLIERINTRODUCE);
        //店铺详情商家信息
        anonymousAntPatterns.add(AnonymousUrlConstant.SHOPDETAILMSG);
        //商品配送地址
        anonymousAntPatterns.add(AnonymousUrlConstant.GETSPECIFICATIONDETAIL);
        //pc 说明设置
        anonymousAntPatterns.add(AnonymousUrlConstant.EXPLAINSETTING_LIST);
        anonymousAntPatterns.add(AnonymousUrlConstant.EXPLAINSETTING_GET);

        //首页
        anonymousAntPatterns.add(AnonymousUrlConstant.HOMEPAGE);
        anonymousAntPatterns.add(AnonymousUrlConstant.LOGINAPI);
        //
        anonymousAntPatterns.add(AnonymousUrlConstant.GETGOODSDETAIL);

        //春节礼包
        anonymousAntPatterns.add(AnonymousUrlConstant.CARDPACKAGE);

        /*不过滤静态文件，兼容前后端不分离模式*/
        anonymousAntPatterns.add("/css/**");
        anonymousAntPatterns.add("/js/**");
        anonymousAntPatterns.add("/fonts/**");
        anonymousAntPatterns.add("/img/**");
        anonymousAntPatterns.add("/docs/**");
        anonymousAntPatterns.add("/druid/**");
        anonymousAntPatterns.add("/upload/**");
        anonymousAntPatterns.add("/files/**");
        anonymousAntPatterns.add("/favicon.ico");
        // TODO: 2022/5/12 自行配置 
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll();

        // 对登录注册要允许匿名访问
        for (String pattern : anonymousAntPatterns) {
            http.authorizeRequests().antMatchers(pattern).permitAll();
        }

        // 禁用 session 此处禁用则无法获取 header中的 Authorization,请勿解开注释
       /* http.sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests().anyRequest().authenticated().and()
                .cors().and()
                .csrf().disable();*/
        //修改X-Frame-Options 允许使用iframe嵌套页面
//        http.headers(headers -> headers
//                .frameOptions(frameOptions -> frameOptions
//                        .sameOrigin()
//                )
//        );
    }

    @Bean
    HuahanCheckHeaderTokenFilter checkHeaderTokenFilter() {
        return new HuahanCheckHeaderTokenFilter(tokenStore, anonymousAntPatterns);
    }

    @Bean
    HuahanSmsVerifyLimitFilter smsVerifyLimitFilter() {
        return new HuahanSmsVerifyLimitFilter(redisHelper, authenticationFailureHandler);
    }

    @Bean
    HuahanLoginVerifyLimitFilter loginVerifyLimitFilter() {
        return new HuahanLoginVerifyLimitFilter(redisHelper, authenticationFailureHandler);
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        // TODO: 2022/5/12 配置资源 ID，需要在 oauth_client_details 表中添加，详细查看数据库脚本
        resources.resourceId(resourceId).stateless(true);
        resources.accessDeniedHandler(accessDeniedHandler);
        resources.authenticationEntryPoint(authenticationEntryPoint);
    }


}
